'use strict'

let models = require('../models');
let errors = require('../../config/errors');

let Student = models.Student;
let Card = models.Card;
let AbsenceApply = models.AbsenceApply;
let AbsenceApplyStatus = models.AbsenceApplyStatus;

let StudentDao = models.StudentDao;
let CardDao = models.CardDao;
let AbsenceApplyDao = models.AbsenceApplyDao;

let userService = require('./user');

function submitAbsenceApply(student, data) {
    let absenceApply = new AbsenceApply({
        status: AbsenceApplyStatus.Processing,
        start: data.start,
        end: data.end,
        student: student,
        comment: data.comment,
        time: new Date()
    });

    AbsenceApplyDao.create(absenceApply);

    return absenceApply;
}

function updateAbsenceApply(student, data) {
    let apply = AbsenceApplyDao.findOne({
        id: data.id
    });

    if ( apply.status != AbsenceApplyStatus.Processing ) {
        throw errors.AbsenceApplyCanNotModified
    }

    apply.start = data.start;
    apply.end = data.end;
    apply.comment = data.comment;

    AbsenceApplyDao.update(apply);

    return apply;
}

function getAppliesOfStudent(student) {
    return AbsenceApplyDao.find({
        student: student.id
    });
}

function getAppliesOfStudents(students, time) {
    let studentIds = students.map(student => student.id);
    let condition = {
        student: {
            $in: studentIds
        }
    };

    if ( time ) {
        condition.time = time;
    }

    return AbsenceApplyDao.find(condition)
}

function getAppliesOfTeacherToday(teacher) {
    let date = new Date();
    let today = new Date(date.getFullYear(), date.getMonth(), date.getDate());
    let tomorrow = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1);

    return teacher.managedClasses.reduce((allApplies, natureClass) => {
        let applies = getAppliesOfStudents(natureClass.students, {
            $gte: today,
            $lte: tomorrow
        });
        return allApplies.concat(applies);
    }, []);
}

function getAppliesOfTeacherBeforeToday(teacher) {
    let date = new Date();
    let today = new Date(date.getFullYear(), date.getMonth(), date.getDate());

    return teacher.managedClasses.reduce((allApplies, natureClass) => {
        let applies = getAppliesOfStudents(natureClass.students, {
            $lt: today
        });
        return allApplies.concat(applies);
    }, []);
}

function getAppliesCountOfTeacher(teacher) {
    return teacher.managedClasses.reduce((appliesCount, natureClass) => {
        let processingApplies = 
                getAppliesOfStudents(natureClass.students)
                .filter(apply => apply.status == AbsenceApplyStatus.Processing);

        return appliesCount + processingApplies.length;
    }, 0);
}

module.exports = {
    submitAbsenceApply,
    getAppliesOfStudent,
    getAppliesOfTeacherToday,
    getAppliesOfTeacherBeforeToday,
    getAppliesCountOfTeacher,
    updateAbsenceApply
};
